package com.laf.web.controller.common;

import cn.hutool.core.img.Img;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.laf.common.config.LafConfig;
import com.laf.common.constant.Constants;
import com.laf.common.core.domain.AjaxResult;
import com.laf.common.core.domain.OCRResult;
import com.laf.common.core.domain.R;
import com.laf.common.exception.ServiceException;
import com.laf.common.utils.FaceUtils;
import com.laf.common.utils.IdOCRUtils;
import com.laf.common.utils.StringUtils;
import com.laf.common.utils.file.FileUtils;
import com.laf.framework.config.ServerConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用请求处理
 *
 * @author ruoyi
 */
@Api(tags = "通用工具管理")
@RestController
@RequestMapping("/common")
@RequiredArgsConstructor
public class CommonController {
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    private final ServerConfig serverConfig;

    private static final String FILE_DELIMETER = ",";

    private final FileStorageService fileStorageService; //注入实列


    private final IdOCRUtils idOCRUtils;

    private final FaceUtils faceUtils;

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @GetMapping("/download")
    @ApiOperation("下载文件")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = LafConfig.getDownloadPath() + fileName;

            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 通用上传请求（单个）
     */
    @PostMapping("/upload")
    @ApiOperation("上传文件")
    public AjaxResult uploadFile(MultipartFile file) throws Exception {
        try {

            // 生成保存文件目录 yyyy/MM/dd/
            String objectName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"));
            FileInfo fileInfo = fileStorageService.of(file.getBytes())
                    .setPath(objectName)
                    .upload();
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", fileInfo.getUrl());
            ajax.put("fileName", fileInfo.getUrl()); // 这里将文件名设置url 的原因是，前端会根据文件名判断是否拼接 http://loalhost/，如果fileName 有已经有了 http 就在拼接 http的前缀路径了
            ajax.put("newFileName", fileInfo.getUrl());
            ajax.put("originalFilename", file.getOriginalFilename());

            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 上传图片，并且检测图片是否是人脸图片 ，
     * 是人脸图片正常返回 url ，不是直接返回 500 即可
     */
    @PostMapping("/upload/face")
    @ApiOperation("上传文件")
    public AjaxResult uploadFileFace(MultipartFile file) throws Exception {
        boolean b = faceUtils.checkIsPortrait(file);
        if (!b) {
            return AjaxResult.error("请上传人脸图片~~");
        }
        AjaxResult ajaxResult = uploadFile(file);
        log.info("返回数据：{}", ajaxResult);
        return ajaxResult;
    }


    /**
     * 通用上传请求（多个）
     */
    @PostMapping("/uploads")
    @ApiOperation("上传文件")
    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception {
        try {
            // 上传文件路径
            String filePath = LafConfig.getUploadPath();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();

            // 生成存储文件目录名
            String objectName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"));
            // 遍历文件数组对象上传文件
            for (MultipartFile file : files) {
                FileInfo fileInfo = fileStorageService.of(file)
                        .setPath(objectName)
                        .upload();
                urls.add(fileInfo.getUrl());
                fileNames.add(fileInfo.getUrl());
                newFileNames.add(FileUtils.getName(fileInfo.getUrl()));
                originalFilenames.add(file.getOriginalFilename());
            }

            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/download/resource")
    @ApiOperation("下载文件")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            if (!FileUtils.checkAllowDownload(resource)) {
                throw new Exception(StringUtils.format("资源文件({})非法，不允许下载。 ", resource));
            }
            // 本地资源路径
            String localPath = LafConfig.getProfile();
            // 数据库资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }


    @PostMapping("/ocr")
    @ApiOperation("身份识别")
    public R<OCRResult> ocrId(MultipartFile frontFile, MultipartFile backFile) {
        OCRResult ocrResult = null;
        try {
            ocrResult = idOCRUtils.identityCardUtilsOCR(frontFile, backFile);
        } catch (Exception e) {
            throw new ServiceException("ocr 识别错误");
        }
        return R.ok(ocrResult);
    }


    @PostMapping("/face")
    @ApiOperation("获取人特征码")
    public R<String> getFaceCode(MultipartFile file) throws IOException {
        int width = 300;
        int height = 400;
        Image image = Img.from(file.getInputStream())
                .cut(new Rectangle(300, 0, 300, 400))
                .getImg();

        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = bufferedImage.createGraphics();
        graphics.drawImage(image, 0, 0, null);

        graphics.dispose();


        // 创建 ByteArrayOutputStream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // 将 BufferedImage 写入 ByteArrayOutputStream
        ImageIO.write(bufferedImage, "png", baos);

        // 将 ByteArrayOutputStream 转换为 byte[]
        byte[] byteArray = baos.toByteArray();

        // 关闭 ByteArrayOutputStream
        baos.close();


        ImageInfo data = ImageFactory.getRGBData(byteArray);
        String faceCode = faceUtils.getFaceCode(data);
        System.out.println("faceCode = " + faceCode);

        return R.ok(faceCode);
    }


}
